package com.xshiwu.springsecurty.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.annotation.Resource;
import javax.sql.DataSource;


@Configuration
public class SecurtyConfigTest extends WebSecurityConfigurerAdapter {


    @Autowired
    private UserDetailsService userDetailsService;

    // 注入数据源
    @Resource
    private DataSource dataSource;

    // 配置Bean对象
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        // 实例化实现类
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        // 加载数据源
        jdbcTokenRepository.setDataSource(dataSource);
        // 是否自动创建数据库
        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }


    /**
     * 重写WebSecurityConfigurerAdapter里面的登录验证接口
     * @param auth 工厂配置类
     * @throws Exception 异常
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }

    @Bean
    public PasswordEncoder password(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * 1、退出功能: logoutUrl
         * 2、logoutSuccessUrl：退出后跳转的页面
         */
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll();
        // 自定义403页面，没有权限的时候跳转该页面
        http.exceptionHandling().accessDeniedPage("/unAuth.html");
        http.formLogin()
                .loginPage("/login.html")                        // 登录页面设置
                .loginProcessingUrl("/user/login")               // 登录访问路径
                .defaultSuccessUrl("/success.html").permitAll()    // 登录成功后跳转路径
                .and().authorizeRequests()
                .antMatchers("/", "/test/hello", "/user/login").permitAll() // 这里面的路径可以直接访问不需认证
                // hasAuthority("/admins"): 表示单用户权限时候进行使用
                // .antMatchers("/test/index").hasAuthority("admins")
                // hasAnyAuthority("admins,manager")：表示可以多个权限用户进行认证
                // .antMatchers("/test/index").hasAnyAuthority("admins,manager")
                // hasRole("xsw")：角色的权限，实现类中需要在名称前加上ROLE_
                .antMatchers("/test/index").hasRole("zs")
                .anyRequest().authenticated()
                // 设计记住我
                .and().rememberMe().tokenRepository(persistentTokenRepository())
                // 设计记住我的有效时长
                .tokenValiditySeconds(60)
                // 查询哪个数据库，后者是对哪个数据库进行操作
                .userDetailsService(userDetailsService)
                .and().csrf().disable();                           // 关闭csrf防护
    }
}
